/*
 * @(#)ANSISequence.java	1.0 Apr 26, 2008
 *
 *	The MIT License
 *
 *	Copyright (c) 2008 Malachi de AElfweald <malachid@gmail.com>
 *
 *	Permission is hereby granted, free of charge, to any person obtaining a copy
 *	of this software and associated documentation files (the "Software"), to deal
 *	in the Software without restriction, including without limitation the rights
 *	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *	copies of the Software, and to permit persons to whom the Software is
 *	furnished to do so, subject to the following conditions:
 *
 *	The above copyright notice and this permission notice shall be included in
 *	all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *	THE SOFTWARE.
 */
package org.eoti.io.charset.ansi.seq;

import org.eoti.io.charset.ansi.ANSICodePoint;

import java.util.*;
import java.util.concurrent.*;

public class ANSISequence
	extends CopyOnWriteArrayList<ANSICodePoint>
{
	protected static ConcurrentHashMap<Integer,ANSICodePoint> ansiMap;
	protected static ConcurrentHashMap<Integer,ANSICodePoint> unicodeMap;
	static{
		ansiMap = new ConcurrentHashMap<Integer,ANSICodePoint>();
		unicodeMap = new ConcurrentHashMap<Integer,ANSICodePoint>();
		for(ANSICodePoint ansiCP : ANSICodePoint.values())
		{
			ansiMap.put(ansiCP.getANSI(), ansiCP);
			ansiMap.put(ansiCP.getUnicode(), ansiCP);
		}
	}


	public enum ValueType{ANSI,Unicode}

	public ANSISequence(List<Integer> codePoints, ValueType type)
	{
		super(convertToANSI(codePoints, type));
	}

	public ANSISequence(String sequence)
	{
		super(convertToANSI(sequence));
	}

	public ANSISequence(ANSICodePoint ... codePoints)
	{
		super(Arrays.asList(codePoints));
	}

	public ANSISequence()
	{
		super();
	}

	public ANSISequence(Collection<? extends ANSICodePoint> c)
	{
		super(c);
	}


	public static int getValue(ANSICodePoint ansiCodePoint, ValueType type)
	{
		switch(type)
		{
			case ANSI:
				return ansiCodePoint.getANSI();
			case Unicode:
				return ansiCodePoint.getUnicode();
		}
		return -1;
	}

	public static ANSICodePoint convertToANSI(int codePoint, ValueType type)
	{
		switch(type)
		{
			case ANSI:
				return ansiMap.get(codePoint);
			case Unicode:
				return unicodeMap.get(codePoint);
		}

		return null;
	}

	public static int switchType(int codePoint, ValueType type)
	{
		return getValue(
			convertToANSI(codePoint, type),
			(type == ValueType.ANSI ? ValueType.Unicode : ValueType.ANSI)
		);
	}

	public static ANSISequence convertToANSI(List<Integer> codePoints, ValueType type)
	{
		ANSISequence toRet = new ANSISequence();
		for(int codePoint : codePoints)
			toRet.add(convertToANSI(codePoint, type));

		return toRet;
	}

	public static ArrayList<Integer> getValues(List<ANSICodePoint> ansiCodePoints, ValueType type)
	{
		ArrayList<Integer> toRet = new ArrayList<Integer>(ansiCodePoints.size());
		for(ANSICodePoint ansiCodePoint : ansiCodePoints)
			toRet.add(getValue(ansiCodePoint, type));

		return toRet;
	}

	public static ANSISequence convertToANSI(String toConvert)
	{
		ArrayList<Integer> unicode = new ArrayList<Integer>(toConvert.length());
		for(int i=0; i<toConvert.length(); i++)
			unicode.add((int)toConvert.charAt(i)); // getCodePointAt doesn't return surrogate pairs directly

		return convertToANSI(unicode, ValueType.Unicode);
	}
}
